home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
001-025
/
scopedisk1
/
semaphorestutor
/
msgsem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-18
|
3KB
|
168 lines
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/ports.h>
#include <exec/semaphores.h>
#include <exec/memory.h>
struct MsgPort *CreatePort();
struct MsgPort *FindPort();
struct XSemaphore *CreateSemaphore();
void DeleteSemaphore();
void *AllocMem();
void cleanup();
struct XSemaphore {
struct Semaphore s;
WORD Users;
};
struct MsgPort *port = 0;
struct XSemaphore *sem = 0;
struct Message msg;
/* I made this extended semaphore so that there is an easy way to
* keep track of when it is safe to delete it. If anyone can think
* of a better way to do this, I'd love to hear it.
*/
extern int Enable_Abort;
main()
{
int i;
Enable_Abort = 0;
/* the existance check/creation must be atomic --> Forbid/Permit */
Forbid();
if (!(sem = (struct XSemaphore *)FindPort("my semaphore")))
sem = CreateSemaphore("my semaphore", 0);
else
sem->Users++;
Permit();
if (!sem) {
printf("Error, can't find *or* create semaphore\n");
cleanup();
exit(100);
}
port = CreatePort(0,0);
if (!port) {
printf("Error, can't create my reply port\n");
cleanup();
}
msg.mn_Node.ln_Type = NT_MESSAGE;
msg.mn_Length = sizeof(struct Message);
msg.mn_ReplyPort = port;
/* for P & V fans, the Procure & Vacate names are mnemonic */
/* - - */
for (i=0;i<5;i++) {
if (!Procure(sem, &msg)) {
WaitPort(port); /* wait for the message to come */
GetMsg(port); /* get it */
}
/* we now have exclusive access */
printf("\nTask $%06x owns the semaphore\n",FindTask(0));
/* pretend to so some action requiring semaphore */
Delay(1 + (rand()&31));
printf("\t\t...semaphore now released\n");
/* yield control to someone else */
Vacate(sem);
/* pretend to so some action not requiring semaphore */
Delay(1 + (rand()&31));
}
cleanup();
}
void cleanup()
{
if (port) {
DeletePort(port);
port = 0;
}
/*
* we'd like to use the semaphore to lock out other users here
* but we'd have to somehow P and then not do a V but delete
* the port instead for this to work... That hurts me more than
* the Forbid() Permit() pair...
*/
if (sem) {
/* the user check/delete must be atomic --> Forbid/Permit */
Forbid();
if (--sem->Users == 0)
DeleteSemaphore(sem);
Permit();
sem = 0;
}
}
struct XSemaphore *CreateSemaphore(name,pri)
char *name;
int pri;
{
struct XSemaphore *s;
char *buf;
s = AllocMem(sizeof(struct XSemaphore), MEMF_PUBLIC|MEMF_CLEAR);
if (!s)
return(0);
s->s.sm_Bids = -1;
NewList(&s->s.sm_MsgPort.mp_MsgList);
s->s.sm_MsgPort.mp_Flags = PA_IGNORE;
s->s.sm_MsgPort.mp_Node.ln_Type = NT_SEMAPHORE;
s->s.sm_MsgPort.mp_Node.ln_Pri = pri;
s->Users = 1;
/* Note that the name must be copied as the original creator
* of the semaphore might exit. We can't leave a pointer to
* the original data segment lying around after the program
* has exited.
*/
if (name) {
buf = AllocMem(strlen(name)+1, MEMF_PUBLIC);
if (!buf) {
FreeMem(s, sizeof(struct XSemaphore));
return(0);
}
strcpy(buf,name);
s->s.sm_MsgPort.mp_Node.ln_Name = buf;
AddPort(s);
}
return(s);
}
void DeleteSemaphore(s)
struct XSemaphore *s;
{
char *name;
if (!s) return;
name = s->s.sm_MsgPort.mp_Node.ln_Name;
if (name) {
RemPort(s); /* remove from list of public semaphores */
FreeMem(name,strlen(name)+1);
}
FreeMem(s, sizeof(struct XSemaphore));
}